package com.hmall.item.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.domain.PageDTO;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.BeanUtils;
import com.hmall.item.domain.dto.ItemDTO;
import com.hmall.item.domain.dto.OrderDetailDTO;
import com.hmall.item.domain.po.Item;
import com.hmall.item.domain.query.ItemPageQuery;
import com.hmall.item.mapper.ItemMapper;
import com.hmall.item.service.IItemService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author itheima
 */
@Service
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public void deductStock(List<OrderDetailDTO> items) {
        String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock";
        boolean r = false;
        try {
            r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity));
        } catch (Exception e) {
            log.error("更新库存异常", e);
//            return;
            throw new BizIllegalException("库存不足！");
        }
        if (!r) {
            throw new BizIllegalException("库存不足！");
        }
    }

    @Override
    public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
        return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
    }

    /**
     * 根据查询条件搜索商品
     * 此方法使用Elasticsearch客户端发送搜索请求，并处理响应以构建分页结果
     *
     * @param itemPageQuery 包含搜索条件和分页信息的查询对象
     * @return 返回一个包含商品列表的PageDTO对象
     * @throws IOException 如果搜索过程中发生I/O错误
     */
    @Override
    public PageDTO<ItemDTO> search(ItemPageQuery itemPageQuery) throws IOException {
        // 创建针对"items"索引的搜索请求
        SearchRequest request = new SearchRequest("items");
        // 构建布尔查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 搜索框
        if (StrUtil.isNotBlank(itemPageQuery.getKey())) {
            boolQuery.must(QueryBuilders.matchQuery("name", itemPageQuery.getKey()));
        } else {
            boolQuery.must(QueryBuilders.matchAllQuery());
        }
        // 分类、品牌、价格
        if (StrUtil.isNotBlank(itemPageQuery.getCategory())) {
            boolQuery.filter(QueryBuilders.termQuery("category", itemPageQuery.getCategory()));
        }
        if (StrUtil.isNotBlank(itemPageQuery.getBrand())) {
            boolQuery.filter(QueryBuilders.termQuery("brand", itemPageQuery.getBrand()));
        }
        if (itemPageQuery.getMinPrice() != null && itemPageQuery.getMaxPrice() != null) {
//            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(itemPageQuery.getMinPrice()).lte(itemPageQuery.getMaxPrice()));
            boolQuery.filter(QueryBuilders.rangeQuery("price").from(itemPageQuery.getMinPrice()).to(itemPageQuery.getMaxPrice()));
        }
        // 设置请求的分页参数
        request.source()
                .from((itemPageQuery.getPageNo() - 1) * itemPageQuery.getPageSize())
                .size(itemPageQuery.getPageSize());
        // 指定排序方式
        if (StrUtil.isNotBlank(itemPageQuery.getSortBy())) {
            request.source().sort(itemPageQuery.getSortBy(), itemPageQuery.getIsAsc() ? SortOrder.ASC : SortOrder.DESC);
        }
        // 高亮设置
        request.source().highlighter(
                SearchSourceBuilder.highlight()
                        .field("name")
                        .requireFieldMatch(false)
        );
        // 将布尔查询设置为请求的查询源
        request.source().query(boolQuery);
        // 执行搜索并获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 初始化用于存储搜索结果的列表
        List<ItemDTO> list = new ArrayList<>();
        // 获取搜索结果的总数量
        long total = Objects.requireNonNull(response.getHits().getTotalHits()).value;
        // 获取搜索结果的文档数组
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            // 将每个搜索结果文档转换为ItemDTO对象并添加到列表中
            ItemDTO itemDTO = JSONUtil.toBean(hit.getSourceAsString(), ItemDTO.class);
            list.add(itemDTO);
        }
        // 计算总页数
        long pages = total % itemPageQuery.getPageSize() == 0 ? total / itemPageQuery.getPageSize() : total / itemPageQuery.getPageSize() + 1;
        // 返回包含总数量、总页数和商品列表的PageDTO对象
        return new PageDTO<>(total, pages, list);
    }

}
